package org.jverify;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.jverify.data.provider.DataProvider;
import org.jverify.data.provider.Db4oOperations;
import org.jverify.utility.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Main is an application that stores and compares hashes of files in any
 * filesystem, and is able to scan for changes in those sums, thus warning you
 * of a possible infected file.
 * 
 * @author Ioannis Mavroukakis
 */
public final class Main {

	private static final String HELP_USAGE = "displays this help info";
	private static final String INITIALISE_USAGE = "initialize db and store file information,this option (re)creates the storage db. Expects a list of directories as arguments";
	private static final String STORE_USAGE = "store compressed contents of the files in the directories provided as arguments to -initialise";
	private static final String VERIFY_USAGE = "compare and verify the files in the database with the files on the system";
	private static final String RESTORE_USAGE = "used in conjuction with -verify to restore corrupt file contents";
	private static final String CONFIG_USAGE = "the location of the configuration file";
	private static final Logger LOG = LoggerFactory.getLogger(Main.class);

	private Main() {
	}

	/**
	 * Application main entry point
	 * 
	 * @param args
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public static void main(final String[] args) throws IOException, InterruptedException {

		final Options options = new Options();
		options.addOption("help", false, HELP_USAGE);
		options.addOption("config", true, CONFIG_USAGE);
		options.addOption("initialise", true, INITIALISE_USAGE);
		options.addOption("store", false, STORE_USAGE);
		options.addOption("verify", false, VERIFY_USAGE);
		options.addOption("restore", false, RESTORE_USAGE);
		options.addOption("refresh", true, VERIFY_USAGE);
		final CommandLineParser parser = new GnuParser();
		final DataProvider dataProvider = new Db4oOperations();
		try {
			final CommandLine cmd = parser.parse(options, args);
			final String configFileName = cmd.getOptionValue("config");
			if (cmd.hasOption("help") || configFileName == null) {
				final HelpFormatter formatter = new HelpFormatter();
				formatter.printHelp("jverify", options);
				return;
			}
			final Properties settings = Settings.load(configFileName);
			if (cmd.hasOption("initialise")) {
				final RunMode runMode = cmd.hasOption("store") ? RunMode.INITIALISE_STORE_CONTENT : RunMode.INITIALISE;
				final FileVerify fileVerify = new FileVerify(runMode, dataProvider);
				LOG.info("Calculating and storing sums,please wait");
				final List<File> files = fileVerify.getFiles(cmd.getOptionValues("initialise"));
				fileVerify.initialise(files);
			}

			if (cmd.hasOption("verify")) {
				final RunMode runMode = cmd.hasOption("restore") ? RunMode.REPLACE : RunMode.VERIFY;
				final FileVerify fileVerify = new FileVerify(runMode, dataProvider);
				LOG.info("Calculating and comparing sums,please wait");
				fileVerify.verify(new EmailAlerter(settings, runMode));
			}

			if (cmd.hasOption("refresh")) {
				final FileVerify fileVerify = new FileVerify(RunMode.REFRESH, dataProvider);
				LOG.info("Calculating and refreshing sums,please wait");
				final List<File> files = fileVerify.getFiles(cmd.getOptionValues("refresh"));
				fileVerify.refresh(files);
			}
			LOG.info("Finished");
		}
		catch (final ParseException e) {
			final HelpFormatter formatter = new HelpFormatter();
			formatter.printHelp("jverify", options, true);
		}
		finally {
			dataProvider.shutdown();
		}
	}
}